package main

import (
	"fmt"
)

type treeNode struct {
	value       int
	left, right *treeNode
}

func (node treeNode) print() {
	fmt.Print(node.value, " ") // root.print()
}

func print(node treeNode) {
	fmt.Print(node.value) // print(root)
}

func (node *treeNode) setValue(value int) { // 只能使用指针才可以改变结构内容
	if node == nil {
		fmt.Println("Settings value to nil node. Ignored.")
		return
	}
	node.value = value
}

func (node *treeNode) traverse() {
	if node == nil {
		return
	}
	node.left.traverse()
	node.print()
	node.right.traverse()

}

func createNode(value int) *treeNode { //工厂函数
	return &treeNode{value: value} //返回局部变量地址
}

func main() {
	var root treeNode
	fmt.Println(root) // {0 <nil> <nil>}
	root = treeNode{value: 3}
	root.left = &treeNode{}
	root.right = &treeNode{5, nil, nil}
	root.right.left = new(treeNode)
	fmt.Println(root)
	root.left.right = createNode(2)
	fmt.Println("==== ", root.left.right)

	nodes := []treeNode{
		{value: 3},
		{},
		{6, nil, &root},
	}
	fmt.Println(nodes)
	fmt.Println(nodes[0].value)
	fmt.Println()

	print(root)
	fmt.Println()
	root.print()

	fmt.Println()
	root.right.left.setValue(6)
	root.right.left.print()
	fmt.Println()

	root.setValue(100)
	print(root)

	fmt.Println()
	pRoot := &root
	pRoot.print()
	fmt.Println()
	pRoot.setValue(200)
	//print(pRoot)  这种方法不会使用指针?
	pRoot.print()
	fmt.Println()

	// todo: nil指针也可以调用方法
	var p *treeNode
	p.setValue(182)
	p = &root
	p.print()
	fmt.Println()
	p.setValue(199)
	p.print()
	fmt.Println()

	root.traverse()
}

/*
todo: 值接收者 vs 指针接收者
- 要改变内容必须使用指针接收者
- 结构过大也要考虑指针接收者
- 一致性: 如有指针接收者,都用指针接收者
- 值接收者是go语言的特性
- 值/指针接收者均可接收值/指针
*/
